#!perl
use strict;
use warnings;

my $max_iter = 100;
my $vdd = 0.3;
my $acc = 0.0005;
my $code_filename = "input2.scs";
my $results_filename = "monteCarlo/mcdata";
our $limith = 0.28;
our $limitl = 0.02;

open (OUTPUT,">bisect_out.txt") or die $!;
close OUTPUT;

open (OUTPUT,">intermed.txt") or die $!;
close OUTPUT;

foreach my $iter (1..$max_iter) {
    my $high_vt_var = $vdd/2;
    my $low_vt_var = -$vdd/2;
    my $last_high_vt_var = 0;
    my $last_low_vt_var = 0;
    my $overflow = 40;
    
    my $high_last = normalize(do_halfiter($iter,$high_vt_var));
    my $low_last = normalize(do_halfiter($iter,$low_vt_var));

    while ( (abs($high_vt_var-$low_vt_var) > ($acc/2)) && ($overflow>0) ) {
        $overflow--;
        
        my $rawh = do_halfiter($iter,$high_vt_var);
        my $rawl = do_halfiter($iter,$low_vt_var);
        my $resh = normalize($rawh);
        my $resl = normalize($rawl);
        
        open (INTERMED,">>intermed.txt") or die $!;
        print INTERMED "<$overflow> <$high_vt_var> <$low_vt_var> <$rawh> <$rawl> <$last_high_vt_var> <$last_low_vt_var> <$resh> <$high_last> <$resl> <$low_last>\n";
        close INTERMED;
        
        if ((($resh==1) && ($resl==0))) {
            $last_high_vt_var = $high_vt_var;
            $last_low_vt_var = $low_vt_var;
            my $temp = $high_vt_var;
            $high_vt_var += abs($high_vt_var-$low_vt_var)/2;
            $low_vt_var += abs($high_vt_var-$low_vt_var)/2;
        }
        elsif (($resh!=1)) {
            my $temp = $last_high_vt_var;
            $last_high_vt_var = $high_vt_var;
            $last_low_vt_var = $low_vt_var;
            $low_vt_var = $high_vt_var;
            $high_vt_var = $temp;
        }
        elsif (($resl!=0)) {
            my $temp = $last_low_vt_var;
            $last_high_vt_var = $high_vt_var;
            $last_low_vt_var = $low_vt_var;
            $high_vt_var = $low_vt_var;
            $low_vt_var = $temp;
        }
        else {
            die "arrooo??"
        }
        
        $high_last=$resh; $low_last=$resl;
    }
    
    open (INTERMED,">>intermed.txt") or die $!;
    print INTERMED "**************\n\n";
    close INTERMED;
        
    open (OUTPUT,">>bisect_out.txt") or die $!;
    print OUTPUT "<$overflow> <$high_vt_var> <$low_vt_var>\n";
    close OUTPUT;
}

close OUTPUT;

sub normalize {
    my ($d) = @_;

    my ($num) = $d =~ /^([\d\.\-]+)/;
    my ($e) = $d =~ /e-(\d+)$/;
    $e += 0;

    $num = $num * (10 ** (-$e));

    return 1 if $num > $limith;
    return 0;
}


sub do_halfiter {
    my ($iter,$vt_var) = @_;
    my $code = get_code($iter,$vt_var);
    open (OCEAN,">$code_filename") or die $!;
    print OCEAN $code;
    close OCEAN;
    system("spectre $code_filename");
    return get_result();
}

sub get_result {
    open (RESULT, "$results_filename") or die $!;
    my $data = <RESULT>;
    chomp $data;
    $data =~ s/\s//g;
    close RESULT;
    return $data
}

sub get_code {
    my ($iter,$vt_var) = @_;
    my $code = << "__NOTOCEAN__";

// Generated for: spectre
// Generated on: Oct 30 00:34:09 2006
// Design library name: SenseAmplifiers
// Design cell name: testbench
// Design view name: schematic
simulator lang=spectre
global 0 vdd!
include "/net/cadence2004/ic50/tools.sun4v/dfII/samples/artist/ahdlLib/quantity.spectre"
parameters vt_var=$vt_var j=1 i=1 h=1 g=1 f=1 e=1 d=3 c=3 b=2 a=3 \\
    precharge_width=100*2*65n q=1e-11
include "models/ptmLib.scs" section=65nmTT
include "models/ptmLib.scs" section=normStat

subckt LatchType BI BL BLN EN ENN SO SON
    P3 (SO EN vdd! vdd!) PFET w=i*130n l=65n
    P2 (SO SON vdd! vdd!) PFET w=f*130n l=65n
    P1 (SON EN vdd! vdd!) PFET w=i*130n l=65n
    P0 (SON SO vdd! vdd!) PFET w=f*130n l=65n
    N8 (net069 EN 0 BI) NFET w=a*130n l=65n
    N5 (SON SO net58 0) NFET w=b*130n l=65n
    N4 (SO SON net53 0) NFET w=b*130n l=65n
    N3 (net53 BLN net069 0) NFET w=d*130n l=65n
    N1 (net58 BL net069 0) NFET w=d*130n l=65n
ends LatchType

// Library name: SenseAmplifiers
// Cell name: precharge
// View name: schematic
subckt precharge IN OUT
    P0 (OUT IN vdd! vdd!) PFET w=precharge_width l=65n
ends precharge
// End of subcircuit definition.

// Library name: SenseAmplifiers
// Cell name: SRAMCell
// View name: schematic
subckt SRAMCell BL BLN WL
    P1 (net25 net14 vdd! vdd!) PFET w=130n l=65n
    P0 (net14 net25 vdd! vdd!) PFET w=130n l=65n
    N3 (BLN WL net14 0) NFET w=130n l=65n
    N2 (BL WL net25 0) NFET w=130n l=65n
    N1 (net25 net14 0 0) NFET w=130n l=65n
    N0 (net14 net25 0 0) NFET w=130n l=65n
ends SRAMCell
// End of subcircuit definition.

// Library name: SenseAmplifiers
// Cell name: testbench
// View name: schematic
I42 (WLN BLD BLN WL WLN SO SON) LatchType
I7 (WL BLN) precharge
I8 (WL BL) precharge
I5 (BL BLN WL) SRAMCell
C5 (BL 0) capacitor c=q
C4 (BLN 0) capacitor c=q

vBLD (BLD BL) vsource dc=vt_var type=dc
include "_graphical_stimuli.scs"
nodeset I5.net25=0.3 I5.net14=0 
ic I5.net25=0 I5.net14=0.3 BLN=0.3 BL=0.3 
simulatorOptions options reltol=1e-3 vabstol=1e-6 iabstol=1e-12 temp=27 \\
    tnom=27 scalem=1.0 scale=1.0 gmin=1e-12 rforce=1 maxnotes=5 maxwarns=5 \\
    digits=5 cols=80 pivrel=1e-3 ckptclock=1800 \\
    sensfile="../psf/sens.output" 
mc1 montecarlo numruns=1 seed=$iter variations=mismatch donominal=yes \\
    scalarfile="../monteCarlo/mcdata" paramfile="../monteCarlo/mcparam" \\
    saveprocessparams=yes processparamfile="../monteCarlo/processParam" \\
    processscalarfile="../monteCarlo/processData" savefamilyplots=yes {
tran tran stop=55n errpreset=liberal write="spectre.ic" \\
    writefinal="spectre.fc" annotate=status maxiters=5 
finalTimeOP info what=oppoint where=rawfile
modelParameter info what=models where=rawfile
element info what=inst where=rawfile
outputParameter info what=output where=rawfile
designParamVals info what=parameters where=rawfile
export rt=oceanEval("value(v(\\"SO\\" ?result 'tran) 55n)")
}
save SO 
saveOptions options save=allpub

__NOTOCEAN__
    
    return $code;
}
